package com.tina.controller;


import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.tina.entity.TiOnline;
import com.tina.entity.TiUsers;
import com.tina.mapper.TiOnlineMapper;
import com.tina.model.ResultFormat;
import com.tina.model.ResultFormatPaging;
import com.tina.service.TiUsersService;
import com.tina.util.*;
import com.tina.util.http.HttpUtils;
import eu.bitwalker.useragentutils.UserAgent;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.FileUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author PIGS
 * @since 2020-06-05
 */
@RestController
@RequestMapping("/tiUsers")
public class TiUsersController {
    private Logger logger = LoggerFactory.getLogger(TiUsersController.class);

    @Autowired
    private TiUsersService tiUsersService;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private SessionDAO sessionDAO;

    @Autowired
    private TiOnlineMapper onlineMapper;

    /**
     * 登录的用户信息保存到在线用户
     * 同一浏览器如果上一个用户没有退出然后返回登录页面进行登录，这时候sessionID是一致的导致存数据的时候是上一次的用户登录的信息
     * 如果登录的时候SESSIONID一致判断当前登录的用户信息用户名是否一致，如果一致就不更改在线用户信息，如果不一致则修改
     */
    public void onlineUser() {
        Collection<Session> sessions = sessionDAO.getActiveSessions();
        for (Session session : sessions) {
            TiOnline userOnline = new TiOnline();
            TiUsers user = new TiUsers();
            SimplePrincipalCollection principalCollection = new SimplePrincipalCollection();
            if (session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY) == null) {
                continue;
            } else {
                principalCollection = (SimplePrincipalCollection) session
                        .getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
                user = (TiUsers) principalCollection.getPrimaryPrincipal();
                userOnline.setOnlineLoginName(user.getUserName());
            }
            userOnline.setOnlineSessionId((String) session.getId());
            userOnline.setOnlineIpaddr("0:0:0:0:0:0:0:1".equals(session.getHost()) ? "127.0.0.1" : session.getHost());
            userOnline.setOnlineStartTimestamp(TimeUtitl.setTime(session.getStartTimestamp()));
            userOnline.setOnlineLastTime(TimeUtitl.setTime(session.getLastAccessTime()));

            UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
            // 获取客户端操作系统
            String os = userAgent.getOperatingSystem().getName();
            // 获取客户端浏览器
            String browser = userAgent.getBrowser().getName();
            userOnline.setOnlineBrowser(browser);
            userOnline.setOnlineOs(os);
            session.setTimeout(1L);
            Long timeout = session.getTimeout();
            if (timeout == 0L) {
                userOnline.setOnlineState(1);
            } else {
                userOnline.setOnlineState(0);
            }
         //   String sendGet = HttpUtils.sendGet("http://ip.taobao.com/outGetIpInfo", "accessKey=alibaba-inc&ip="+userOnline.getOnlineIpaddr());
         //   userOnline.setOnlineLoginLocation(sendGet);
            Integer outTime = Math.toIntExact(timeout);
            userOnline.setOnlineExpireTime(outTime);
            TiOnline online = onlineMapper.selectById(userOnline);
            logger.info("online={}", online);
            if (online == null) {
                Integer insertOnline = onlineMapper.insert(userOnline);
                logger.info("insertOnline={}", insertOnline);
            } else if (online != null) {
                if (online.getOnlineSessionId().equals(session.getId())) {
                    Integer updateOnlineById = onlineMapper.updateById(userOnline);
                    logger.info("updateOnlineById={}", updateOnlineById);
                } else if (!online.getOnlineLoginName().equals(userOnline.getOnlineLoginName())) {
                    Integer updateOnlineById = onlineMapper.updateById(userOnline);
                    logger.info("updateOnlineById={}", updateOnlineById);
                }
            }
        }
    }

    /**
     * 如果登录成功就统计在线用户
     *
     * @param tiUsers
     * @return
     */
    @PostMapping("login")
    @ApiOperation(value = "用户登录")
    @CrossOrigin
    public ResultFormat tiUsersLogin(TiUsers tiUsers) {
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(tiUsers.getUserName(), tiUsers.getUserPassword());
        try {
            subject.login(token);
            if (subject.isAuthenticated()) {
                logger.info("登录成功");
                onlineUser();
                return ResultUtil.success(200, "登录成功");
            }
        } catch (LockedAccountException l) {
            logger.info("账号不存在：");
            return ResultUtil.error(100, "账户已被锁定");
        } catch (UnknownAccountException e) {
            logger.info("账号不存在：");
            return ResultUtil.error(404, "账号不存在");
        } catch (IncorrectCredentialsException ice) {
            logger.info("密码错误：");
            return ResultUtil.error(100, "密码输入错误");
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("发生错误={}", e.getMessage());
        }

        return ResultUtil.error(500, "稍后重试！");
    }

    /**
     * 查询用户列表
     * 并分页
     * 首先是从service返回的数据
     * 再从shiro中获取当前登录的用户
     * 然后过滤掉当前登录的用户
     *
     * @param tiUsers
     * @param page
     * @param limit
     * @return
     */
    @GetMapping("queryUserList")
    @ApiOperation(value = "查询用户列表")
    ResultFormatPaging queryUserList(TiUsers tiUsers, @RequestParam("page") Integer page, @RequestParam("limit") Integer limit) {
        logger.info("tiUsers={}", tiUsers);
        IPage<TiUsers> tiUsersIPage = tiUsersService.queryUserList(tiUsers, page, limit);
        List<TiUsers> records = tiUsersIPage.getRecords();
        Subject subject = SecurityUtils.getSubject();
        TiUsers tiUsersSubject = (TiUsers) subject.getPrincipal();
        List<TiUsers> collect = records.stream().filter(TiUsers -> !(TiUsers.getUserId().equals(tiUsersSubject.getUserId()))).collect(Collectors.toList());
        return ResultPagingUtil.pagingSuccess(0, tiUsersIPage.getTotal(), collect);
    }

    /**
     * 查询用户信息
     *
     * @return
     */
    @PostMapping("queryUserInfo")
    @ApiOperation(value = "查询用户信息")
    ResultFormat queryUserInfo(TiUsers tiUsers) {
        logger.info("tiUsers={}", tiUsers);
        TiUsers tiUsers1 = tiUsersService.queryUserInfo(tiUsers);
        if (tiUsers1 != null) {
            return ResultUtil.success(tiUsers1);
        }
        return ResultUtil.success(100, "暂无数据..");
    }

    /**
     * 通过id查询用户信息
     *
     * @return
     */
    @GetMapping("getShiroUserInfo")
    @ApiOperation(value = "通过id查询用户信息")
    ResultFormat getShiroUserInfo() {
        Subject subject = SecurityUtils.getSubject();
        TiUsers tiUsersSubject = (TiUsers) subject.getPrincipal();
        return ResultUtil.success(tiUsersSubject);
    }

    /**
     * 修改 用户 状态
     *
     * @param userState
     * @param userId
     * @return
     */
    @PutMapping("updateUserState")
    @ApiOperation(value = "修改用户状态")
    public ResultFormat updateUserState(Integer userState, Long userId) {
        TiUsers tiUsers = new TiUsers();
        logger.info("userState,userId={}", userState + " -- " + userId);

        if (userState != null && userId != null) {
            tiUsers.setUserId(userId);
            tiUsers.setUserState(userState);
            if (tiUsers.getUserState() == 1) {
                Long delete = redisUtil.delete("tiUsers:" + userId);
                logger.info("delete={}", delete);
            }
            tiUsers.setUserRegistrationTime(null);
            boolean update = tiUsersService.updateById(tiUsers);
            logger.info("update={}", update);

            return ResultUtil.success(update);
        }

        return ResultUtil.error(100, "修改失败");
    }

    /**
     * 修改 用户信息
     *
     * @param tiUsers
     * @param roleId
     * @param request
     * @return
     */
    @PutMapping("editUser")
    @ApiOperation(value = "修改用户信息")
    public ResultFormat editUser(TiUsers tiUsers, Integer roleId, HttpServletRequest request) throws Exception {

        logger.info("tiUsers={}", tiUsers);
        logger.info("roleId={}", roleId);
        Integer editUser = tiUsersService.editUser(tiUsers, roleId);
        logger.info("editUser={}", editUser);
        if (editUser == 1) {
            return ResultUtil.success(editUser, "操作成功");
        }

        if (editUser == 101) {
            return ResultUtil.success(101, "用户名已存在");
        }

        return ResultUtil.error(100, "操作失败");
    }

    /**
     * 修改当前登录用户信息
     *
     * @param tiUsers
     * @param roleId
     * @param request
     * @return
     */
    @PutMapping("editThisLoginUser")
    @ApiOperation(value = "修改当前登录用户信息")
    public ResultFormat editThisLoginUser(TiUsers tiUsers, Integer roleId, HttpServletRequest request) throws Exception {

        logger.info("tiUsers={}", tiUsers);
        logger.info("roleId={}", roleId);
        Integer editThisLoginUser = tiUsersService.editThisLoginUser(tiUsers, roleId);
        logger.info("editThisLoginUser={}", editThisLoginUser);
        if (editThisLoginUser == 1) {
            return ResultUtil.success(editThisLoginUser, "操作成功");
        }
        if (editThisLoginUser == 101) {
            return ResultUtil.success(101, "用户名已存在");
        }

        return ResultUtil.error(100, "操作失败");
    }

    /**
     * 添加用户
     *
     * @return
     */
    @PostMapping("saveUser")
    @ApiOperation(value = "添加用户")
    public ResultFormat saveUser(TiUsers tiUsers, Integer roleId, HttpServletRequest request) throws Exception {
        Integer integer = tiUsersService.saveUser(tiUsers, roleId);
        return ResultUtil.success(integer, "操作成功");
    }

    /**
     * 修改用户头像
     * 接受 base64 传过来的字节码
     *
     * @param
     * @return
     */
    @PutMapping("/editUserImage")
    @ApiOperation(value = "修改用户头像")
    public ResultFormat editUserImage(@RequestParam(value = "img", required = false) String img) throws IOException {

        long startTime = System.currentTimeMillis();
        MultipartFile myFile = Bse64ToMultipartUtil.base64ToMultipart(img);

        if (!myFile.isEmpty()) {
            logger.info("文件类型={}", myFile.getContentType());
            logger.info("文件大小={}", myFile.getSize());
            logger.info("文件原名称={}", myFile.getOriginalFilename());
            String myFileOriginalFilename = myFile.getOriginalFilename();
            FileUtils.copyInputStreamToFile(myFile.getInputStream(), new File("/usr/apk/apache-tomcat-9.0.22/webapps/images/", myFileOriginalFilename));
            logger.info("上传成功");

            /**
             * 上传成功之后保存到tomcat容器中
             */
            Subject subject = SecurityUtils.getSubject();
            TiUsers tiUsersSubject = (TiUsers) subject.getPrincipal();

            TiUsers tiUsers = new TiUsers();
            AbstractWrapper wrapper = new QueryWrapper();
            if (tiUsersSubject != null) {
                wrapper.eq("user_id", tiUsersSubject.getUserId());
                tiUsers.setUserProfilePhoto("http://pigs.gold:8762/images/" + myFileOriginalFilename);
                tiUsersSubject.setUserProfilePhoto("http://pigs.gold:8762/images/" + myFileOriginalFilename);
                boolean update = tiUsersService.update(tiUsers, wrapper);
                logger.info("flag = {}", update);
                if (update) {
                    return ResultUtil.success();
                }
            }
        }
        return ResultUtil.error();
    }


    /**
     * 修改用户密码
     *
     * @param tiUsers
     * @param formerPwd
     * @return
     */
    @PostMapping("editUserPwd")
    @ApiOperation(value = "修改用户密码")
    public ResultFormat editUserPwd(TiUsers tiUsers, String formerPwd) {
        Integer editUserPwd = tiUsersService.editUserPwd(tiUsers, formerPwd);
        logger.info("editUserPwd={}", editUserPwd);
        String msg = "";
        if (editUserPwd == 101) {
            msg = "旧密码输入错误";
        } else if (editUserPwd == 1) {
            msg = "操作成功";
        } else {
            msg = "操作失败";
        }
        return ResultUtil.success(editUserPwd, msg);
    }

}
